package lilypad.bukkit.connect.injector; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.socket.SocketChannel; import java.net.InetSocketAddress; import java.lang.reflect.Method; import java.util.List; import lilypad.bukkit.connect.ConnectPlugin; import lilypad.bukkit.connect.util.ReflectionUtils; import org.bukkit.Server; public class NettyInjector { @SuppressWarnings("unchecked") public static int injectAndFindPort(Server server, NettyInjectHandler handler) throws Exception { Method serverGetHandle = server.getClass().getDeclaredMethod("getServer"); Object minecraftServer = serverGetHandle.invoke(server); // Get Server Connection Method serverConnectionMethod = null; for(Method method : minecraftServer.getClass().getSuperclass().getDeclaredMethods()) { if(!method.getReturnType().getSimpleName().equals("ServerConnection")) { continue; } serverConnectionMethod = method; break; } Object serverConnection = serverConnectionMethod.invoke(minecraftServer); // Get ChannelFuture List // TODO find the field dynamically List<ChannelFuture> channelFutureList = ReflectionUtils.getPrivateField(serverConnection.getClass(), serverConnection, List.class, ConnectPlugin.getProtocol().getNettyInjectorChannelFutureList()); // Iterate ChannelFutures int commonPort = 0; for(ChannelFuture channelFuture : channelFutureList) { // Get ChannelPipeline ChannelPipeline channelPipeline = channelFuture.channel().pipeline(); // Get ServerBootstrapAcceptor ChannelHandler serverBootstrapAcceptor = channelPipeline.last(); // Get Old ChildHandler ChannelInitializer<SocketChannel> oldChildHandler = ReflectionUtils.getPrivateField(serverBootstrapAcceptor.getClass(), serverBootstrapAcceptor, ChannelInitializer.class, "childHandler"); // Set New ChildHandler ReflectionUtils.setFinalField(serverBootstrapAcceptor.getClass(), serverBootstrapAcceptor, "childHandler", new NettyChannelInitializer(handler, oldChildHandler)); // Update Common Port commonPort = ((InetSocketAddress) channelFuture.channel().localAddress()).getPort(); } return commonPort; } }